package com.rzjm.api.controller;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rzjm.api.constant.ResponseCode;
import com.rzjm.api.entity.*;
import com.rzjm.api.pay.utils.RSA;
import com.rzjm.api.pay.wxpay.WXPayCommonUtil;
import com.rzjm.api.pay.wxpay.WxAppPay;
import com.rzjm.api.service.*;
import com.rzjm.api.util.*;

import com.vdurmont.emoji.EmojiParser;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.*;

/**
 *@Author: ZhouWei
 *@Description:  订单列表
 *@Date 2018-05-10
 */
@Component
@RestController
@RequestMapping("/pay")//url:模块/资源/{}/细分
public class PayController extends BaseController{

    @Resource
    private UserService userService;
    @Resource
    private UserMpService userMpService;
    @Resource
    private MsgTemplateService msgTemplateService;
    @Resource
    private WxTemplateService wxTemplateService;
    @Resource
    private SplitAccountService splitAccountService;
    @Resource
    private WxUserCashRecordService wxUserCashRecordService;
    @Resource
    private ParameterService parameterService;
    @Resource
    private ChargerOrderService chargerOrderService;



    @Value("${web.wx_notify_url}")
    private String wx_notify_url;//微信支付的回调地址

    @Value("${web.keyPath}")
    private String keyPath;//微信支付的回调地址

    @Value("${web.wx_refund_notify_url}")
    private String wx_refund_notify_url;//微信支付的回调地址

    @Value("${web.wx_refund_balance_notify_url}")
    private String wx_refund_balance_notify_url;//微信支付的回调地址

    @Value("${web.appid}")
    private String appid;
    @Value("${web.secret}")
    private String secret;
    @Value("${web.mch_id}")
    private String mch_id;
    @Value("${web.api_key}")
    private String api_key;

    @Value("${web.appidMp}")
    private String appidMp;//公众号appid
    @Value("${web.secretMp}")
    private String secretMp;//公众号secret

    /**
     * 调起支付
     * @return
     */
    @PostMapping(value = "/test")
    public JSONObject test(@RequestBody String requestParam, HttpServletRequest request){
        JSONObject ret = null;
        try{
            JSONObject jsonRequest = JSONUtil.parseObj(requestParam);
            int user_id = jsonRequest.containsKey("user_id") ? jsonRequest.getInt("user_id") : 0;
            long order_id = jsonRequest.containsKey("order_id") ? jsonRequest.getInt("order_id") : 0L;

            ChargerOrder order = chargerOrderService.findById(order_id);
            User user = userService.findById(user_id);
            sendWxMsg(user, order, 7);
        }catch (Exception e){
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * 调起退款(发起退款操作)
     * @return
     */
    @PostMapping(value = "/requestRefund")
    public JSONObject requestRefund(@RequestBody String requestParam, HttpServletRequest request){
        JSONObject ret = null;
        try{
            JSONObject jsonRequest = JSONUtil.parseObj(requestParam);
            int user_id = jsonRequest.containsKey("user_id") ? jsonRequest.getInt("user_id") : 0;
            long order_id = jsonRequest.containsKey("order_id") ? jsonRequest.getInt("order_id") : 0L;

            boolean blIsMineOrder = false;
            User user = userService.findById(user_id);
            if(user == null){
                return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该用户不存在"),true,true);
            }

            ChargerOrder orders = chargerOrderService.findById(order_id);
            if(orders != null){
                blIsMineOrder = true;
                String out_refund_no = OrderUtil.getOrderNoByTimespan();
                orders.setRefundOutTradeNo(out_refund_no);
            }

            if(blIsMineOrder){
                WxAppPay wxAppPay = new WxAppPay(wx_refund_notify_url, secret, appid, mch_id,api_key);
                String retRequest = wxAppPay.refundPayAPI(orders.getOutTradeNo(),orders.getPayPrice(),orders.getPayPrice(),orders.getRefundOutTradeNo(),keyPath);
                ret = Tools.getJson(new GsonResultBean<>(ResponseCode.OK,"请求成功",retRequest),true,false);
                //订单状态 0 - 未支付   1 - 支付中  2 - 已支付（待核销）  3 - 已核销
                // 4 - 已评价  5 - 订单取消  6 - 发起退货  7 - 同意退货(退货处理中)  8 - 退货完成  9 - 拒绝退货
                orders.setStatus(7);//同意退货
                chargerOrderService.updateById(orders);
            }else{//当前订单不属于您
                ret = Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"当前订单不属于您"),true,true);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * 微信支付退款回调处理
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/wxpay_refund_notify")
    public String wxPayRefundNotify(HttpServletRequest request) throws IOException {
        System.out.println("微信支付退款回调");
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        int ret = 0;
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultXml = new String(outSteam.toByteArray(), "utf-8");
        System.out.println("微信退款处理成功回调:" + resultXml);
        Map<String, String> params = null;
        try {
            params = WXPayCommonUtil.doXMLParse(resultXml);
        } catch (JDOMException e) {
            e.printStackTrace();
        }
        outSteam.flush();
        outSteam.close();
        inStream.close();
        System.out.println("===============退款处理成功==============");
        // ------------------------------
        // 处理业务开始
        // ------------------------------
        // 此处处理订单状态，结合自己的订单数据完成订单状态的更新
        // ------------------------------
        String return_code = params.get("return_code");
        String attach = params.get("attach");
        System.out.println("附加信息: " + attach);
        String req_info = params.get("req_info");
        try {
            if(return_code.equals("SUCCESS")){
                String descrypt = RSA.descrypt(req_info,api_key);
                Map<String,String> reqInfoMap = WXPayCommonUtil.doXMLParse(descrypt);
                ret = refund_success_charger(reqInfoMap);
                if(ret > 0){
                    return "success";
                }else{
                    return "fail";
                }
            }
            return "fail";
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 处理业务完毕
        // ------------------------------
        return "fail";
    }

    /**
     * 商品订单的 退款成功处理
     * @param params
     * @return
     */
    @SuppressWarnings("unchecked")
    private int refund_success_charger(Map<String, String> params){
        String out_trade_no = params.get("out_trade_no");// 本平台  商户订单号
        int ret = 0;
        try{
            QueryWrapper<ChargerOrder> qw = new QueryWrapper<>();
            qw.eq("out_trade_no",out_trade_no);
            ChargerOrder order = chargerOrderService.getOne(qw);
            if(order != null){
                User user = userService.findById(order.getUserId());
                //订单状态 0 - 未支付   1 - 支付中  2 - 已支付  3 - 充电中  4 - 已发起退款  5 - 退款完成  6 - 退款失败  8 - 订单已完成（结束）
                if(order.getStatus() == 4) {//发起退款 并同意申请 的才执行
                    String refund_fee = "";//  订单金额
                    String trade_no = "";//  订单号
                    double refund_fee_double = 0;

                    refund_fee = params.get("refund_fee");
                    trade_no = params.get("transaction_id");//微信支付订单号
                    refund_fee_double = Double.valueOf(refund_fee) / 100;

                    //订单状态 0 - 未支付   1 - 支付中  2 - 已支付  3 - 充电中  4 - 已发起退款  5 - 退款完成  6 - 退款失败  8 - 订单已完成（结束）
                    order.setStatus(5);
                    order.setTransactionId(trade_no);
                    //0 未退款 1 申请中 2 已退款
                    order.setRefundStatus(2);
                    order.setRefundPrice(new BigDecimal(refund_fee_double));
                    order.setRefundReasonTime(new Date());
//                    ret = chargerOrderService.buyNormalUpdate(order);
                    if(ret > 0){
                        //退款成功通知
                        sendWxMsgRefund(user,order,4);
                    }
                    System.out.println("=====支付成功====");
                    logger.info("普通商品订单号：" + out_trade_no + "支付成功");
                }
            }else{
                System.out.println("普通商品订单号：" + out_trade_no + "不存在");
                logger.error("普通商品订单号：" + out_trade_no + "不存在");
            }
        }catch (Exception ex){
            ex.printStackTrace();
            System.out.println(ex.getMessage());
        }
        return ret;
    }

    /**
     *  订单支付成功 公众号推送消息
     * @param user
     * @param order
     * @param template_type
     * @return
     */
    public int sendWxMsg(User user, ChargerOrder order, Integer template_type){
        try{
            QueryWrapper<UserMp> qw = new QueryWrapper<>();
//            qw.eq("mer_id",order.getMerId());
            List<UserMp> userMps = userMpService.list(qw);
            String accessToken = WxMessage.getACCESSTOKEN(appidMp,secretMp);
            if(userMps != null && userMps.size() > 0){
                for(UserMp userMp : userMps){
                    WxMsgTemplate template = null;
                    if(template_type == 7){//支付成功发送推送消息到 商家管理员微信上
                        template = getTemplateToMerManager(userMp,order,template_type);
                    }
                    String param = JSONUtil.parseObj(template).toString();
                    JSONObject jsonObject = WxMessage.sendMsg(accessToken,param);
                    System.out.println("公众号推送消息 - 商家端响应信息:" + jsonObject.toString());
                }
            }
            WxMsgTemplate template = getTemplateToUser(user,order,3);
            String param = JSONUtil.parseObj(template).toString();
            JSONObject jsonObject = WxMessage.sendMsg(accessToken,param);
            System.out.println("公众号推送消息 - 用户端响应信息:" + jsonObject.toString());

        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage(), e);
            System.out.println("发送失败" + e.getMessage());
        }
        return 1;
    }

    /**
     *  普通订单退款成功 公众号推送消息
     * @param user
     * @param order
     * @param template_type
     * @return
     */
    public int sendWxMsgRefund(User user, ChargerOrder order, Integer template_type){
        try{
            if(order != null){
                String accessToken = WxMessage.getACCESSTOKEN(appidMp,secretMp);
                //给用户发送支付成功消息
                WxMsgTemplate template = getTemplateToUserByRefund(user,order,template_type);
                String param = JSONUtil.parseObj(template).toString();
                JSONObject jsonObject = WxMessage.sendMsg(accessToken,param);
                System.out.println("公众号推送消息 - 用户端响应信息:" + jsonObject.toString());
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage(), e);
            System.out.println("发送失败" + e.getMessage());
        }
        return 1;
    }

    /**
     *  发送推送消息到 商家管理员微信上
     * @param user
     * @param order
     * @param template_type
     * @return
     */
    private WxMsgTemplate getTemplateToUser(User user, ChargerOrder order, Integer template_type){
        WxMsgTemplate template = new WxMsgTemplate();
        WxTemplate wxTemplate = wxTemplateService.selectByUniqueColumn("template_type",template_type);
        UserMp userMp = userMpService.selectByUniqueColumn("union_id",user.getUnionId());
        if(userMp != null){
            template.setTouser(userMp.getOpenId());
            template.setTemplate_id(wxTemplate.getTemplateId());
            template.setUrl("");

            Map<String,Object> miniprogram = new HashMap<>();
            miniprogram.put("appid",appid);
            miniprogram.put("pagepath","pages/order/productList/index?state=0");
            template.setMiniprogram(miniprogram);

            Map<String, MsgTempData> m = new HashMap<String, MsgTempData>();
            //您好，您的订单支付成功！
            //订单号：JPH81
            //支付金额：200元
            //支付时间：2016-04-01 12:32
            //感谢您的使用
            MsgTempData first = new MsgTempData();
            first.setColor(wxTemplate.getFontColor());
            first.setValue("尊敬的业主您好，您的订单支付成功！");
            m.put("first",first);

            //订单号
            MsgTempData keyword1 = new MsgTempData();
            keyword1.setColor(wxTemplate.getFontColor());
            keyword1.setValue(order.getOrderNo().toUpperCase());
            m.put("keyword1",keyword1);

            //支付金额
            MsgTempData keyword2 = new MsgTempData();
            keyword2.setColor(wxTemplate.getFontColor());
            keyword2.setValue(MathUtil.getDoubleUp(order.getPayPrice().doubleValue()) + "元");
            m.put("keyword2",keyword2);

            //支付时间
            MsgTempData keyword3 = new MsgTempData();
            keyword3.setColor(wxTemplate.getFontColor());
            keyword3.setValue(DateUtil.getTime(order.getPayTime()));
            m.put("keyword3",keyword3);

            MsgTempData remark = new MsgTempData();
            remark.setColor(wxTemplate.getFontColor());
            remark.setValue("感谢您的使用");
            m.put("remark",remark);

            template.setData(m);
        }
        return template;
    }

    /**
     *  发送推送消息到 商家管理员微信上
     * @param user
     * @param order
     * @param template_type
     * @return
     */
    private WxMsgTemplate getTemplateToUserByRefund(User user, ChargerOrder order, Integer template_type){
        WxMsgTemplate template = new WxMsgTemplate();
        WxTemplate wxTemplate = wxTemplateService.selectByUniqueColumn("template_type",template_type);
        UserMp userMp = userMpService.selectByUniqueColumn("union_id",user.getUnionId());
        if(userMp != null){
            template.setTouser(userMp.getOpenId());
            template.setTemplate_id(wxTemplate.getTemplateId());
            template.setUrl("");

            Map<String,Object> miniprogram = new HashMap<>();
            miniprogram.put("appid",appid);
            miniprogram.put("pagepath","pages/order/productList/index?index=0");
            template.setMiniprogram(miniprogram);

            Map<String, MsgTempData> m = new HashMap<String, MsgTempData>();
//            {{first.DATA}}
//            订单号：{{keyword1.DATA}}
//            商品：{{keyword2.DATA}}
//            退款金额：{{keyword3.DATA}}
//            客户名称：{{keyword4.DATA}}
//            退款原因：{{keyword5.DATA}}
//            {{remark.DATA}}
            MsgTempData first = new MsgTempData();
            first.setColor(wxTemplate.getFontColor());
            first.setValue("尊敬的业主您好，您的订单已退款完成！");
            m.put("first",first);

            //订单号
            MsgTempData keyword1 = new MsgTempData();
            keyword1.setColor(wxTemplate.getFontColor());
            keyword1.setValue(order.getOrderNo().toUpperCase());
            m.put("keyword1",keyword1);

            //商品
            MsgTempData keyword2 = new MsgTempData();
            keyword2.setColor(wxTemplate.getFontColor());
//            Product product = productService.getProductByOrderId(order.getId());
//            if(product!=null){
//                keyword2.setValue(product.getStoreName());
//            }else{
//                keyword2.setValue("商品不存在");
//            }
            m.put("keyword2",keyword2);

            //客户名称
            MsgTempData keyword3 = new MsgTempData();
            keyword3.setColor(wxTemplate.getFontColor());
            keyword3.setValue(EmojiParser.parseToUnicode(user.getNickName()));
            m.put("keyword3",keyword3);

            //退款金额
            MsgTempData keyword4 = new MsgTempData();
            keyword4.setColor(wxTemplate.getFontColor());
            keyword4.setValue(MathUtil.getDoubleUp(order.getRefundPrice().doubleValue())+"");
            m.put("keyword4",keyword4);

            //备注信息
            MsgTempData remark = new MsgTempData();
            remark.setColor(wxTemplate.getFontColor());
            remark.setValue("感谢您的使用,退款金额以到账为准");
            m.put("remark",remark);

            template.setData(m);
        }
        return template;
    }

    /**
     *  发送推送消息到 商家管理员微信上
     * @param userMp
     * @param order
     * @param template_type
     * @return
     */
    private WxMsgTemplate getTemplateToMerManager(UserMp userMp, ChargerOrder order, Integer template_type){
        WxMsgTemplate template = new WxMsgTemplate();
        WxTemplate wxTemplate = wxTemplateService.selectByUniqueColumn("template_type",template_type);
        if(userMp != null){
            template.setTouser(userMp.getOpenId());
            template.setTemplate_id(wxTemplate.getTemplateId());
            template.setUrl("");

            Map<String,Object> miniprogram = new HashMap<>();
            miniprogram.put("appid",appid);
            miniprogram.put("pagepath","/pages/order/merList/index?state=0");
            template.setMiniprogram(miniprogram);

            Map<String, MsgTempData> m = new HashMap<String, MsgTempData>();
//            有客户要看房啦，请及时处理
//            提交时间：2018-07-09
//            订单类型：看房
//            客户信息：张丽 电话：1111111111111
//            房屋信息：杭州市西湖区湖墅南路111号
//            感谢您的使用。
            MsgTempData first = new MsgTempData();
            first.setColor(wxTemplate.getFontColor());
            first.setValue("尊敬的商家用户您好，您有新客户订单");
            m.put("first",first);

            //提交时间
            MsgTempData keyword1 = new MsgTempData();
            keyword1.setColor(wxTemplate.getFontColor());
            keyword1.setValue(DateUtil.getSdfTimesCN());
            m.put("keyword1",keyword1);

            //订单类型
            MsgTempData keyword2 = new MsgTempData();
            keyword2.setColor(wxTemplate.getFontColor());
            keyword2.setValue("商家服务");
            m.put("keyword2",keyword2);

            //客户信息
            MsgTempData keyword3 = new MsgTempData();
            keyword3.setColor(wxTemplate.getFontColor());
//            keyword3.setValue(order.getRealName() + "(" + order.getUserPhone()+")");
            m.put("keyword3",keyword3);

            //房屋信息
            MsgTempData keyword4 = new MsgTempData();
            keyword4.setColor(wxTemplate.getFontColor());
//            keyword4.setValue(order.getUserAddress());
            m.put("keyword4",keyword4);

            MsgTempData remark = new MsgTempData();
            remark.setColor(wxTemplate.getFontColor());
            remark.setValue("客户已下单，请及时跟进处理");
            m.put("remark",remark);

            template.setData(m);
        }
        return template;
    }

}
